﻿using CLVisionHalconWorker;
using HalconDotNet;
using NationalInstruments.TestStand.Interop.API;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CLVisionHalconTS
{
    public class HalconCallerTS : HalconCaller
    {
        private HalconCallerTS()
        {

        }

        //创建唯一实例
        private volatile static HalconCallerTS halconCallerTS ;
        //创建锁
        private static object o = new object();
        //通过方法，返回实例
        public static HalconCallerTS GetHalconCallerTSInstance()
        {
            if (halconCallerTS == null)
            {
                lock (o)
                {
                    if (halconCallerTS == null)
                    {
                        halconCallerTS = new HalconCallerTS();
                    }
                }
            }
            return halconCallerTS;
        }

        List<HObject> hInputIconics;
        List<HTuple> hInputControls;



        public  bool CallProcedureTS(string procedureName, PropertyObject InputIconics, PropertyObject InputControls, PropertyObject OutputIconics, PropertyObject OutputControls, out int ErrorCode, out string ErrorText)
        {
            string _hErrorMsg = "";

            hInputIconics = new List<HObject>();
            hInputControls = new List<HTuple>();

            try
            {
                HOperatorSet.SetSystem("legacy_handle_mode", "true");
                HOperatorSet.SetSystem("clip_region", "false");
                base.LoadProcedure(procedureName, out ErrorCode, out ErrorText);
                base.GetProcedureParNames(out ErrorCode, out ErrorText);

                int _InputIconicLength = base.InputIconicNames.Length;
                int _InputCtrlLength = base.InputCtrlNames.Length;
                int _OutputIconicLength = base.OutputIconicNames.Length;
                int _OutputCtrlLength = base.OutputCtrlNames.Length;

                //1、InputIconic变量输入
                int _NumInputIconics = InputIconics.GetNumSubProperties("");
                if (_InputIconicLength != 0)
                {
                    if (_InputIconicLength == _NumInputIconics)
                    {
                        //提取InputIconics里的子节点以及子节点里存储的值（Number/String/Boolean等）
                        PropertyObject[] _TS_InputIconic = InputIconics.GetSubProperties("", 0);
                        for (int i = 0; i < _InputIconicLength; i++)
                        {
                            int _Num_TSInputIconic = _TS_InputIconic[i].GetNumElements();
                            PropertyObjectType _type_TSInputIconic = _TS_InputIconic[i].Type;
                            string _typeName_TSInputIconic = _type_TSInputIconic.DisplayString;
                            switch (_typeName_TSInputIconic.Split('[')[0])
                            {
                                default:
                                    break;

                                case "Array of Numbers":
                                    for (int j = 0; j < _Num_TSInputIconic; j++)
                                    {
                                        long _number = (long)_TS_InputIconic[i].GetValNumberByOffset(j, 0);
                                        HOperatorSet.DeserializeObject(out HObject objectVal, _number);
                                        hInputIconics.Add(objectVal);
                                    }
                                    break;

                                case "Array of Strings":
                                    for (int j = 0; j < _Num_TSInputIconic; j++)
                                    {
                                        string _string = _TS_InputIconic[i].GetValStringByOffset(j, 0);
                                        HOperatorSet.DeserializeObject(out HObject objectVal, Convert.ToInt64(_string));
                                        hInputIconics.Add(objectVal);
                                    }
                                    break;
                            }
                        }
                    }
                    else
                    {
                        ErrorCode = -1;
                        ErrorText = procedureName + "：CallProcedure Fail!，hProcedure输入参数(InputIconic)个数与Locals对应的参数个数不一致！";
                        // Trace.Error(ErrorText);
                        return false;
                    }
                }

                //2、InputControl变量输入
                int _NumInputControls = InputControls.GetNumSubProperties("");
                if (_InputCtrlLength != 0)
                {
                    if (_InputCtrlLength == _NumInputControls)
                    {
                        //提取InputControls里的子节点以及子节点里存储的值（Number/String/Boolean等）
                        PropertyObject[] _TS_InputControl = InputControls.GetSubProperties("", 0);
                        for (int i = 0; i < _InputCtrlLength; i++)
                        {
                            PropertyObjectType _type_TSInputControl = _TS_InputControl[i].Type;
                            string _typeName_TSInputControl = _type_TSInputControl.DisplayString;

                            var _Num_TSInputControl = _TS_InputControl[i].GetNumElements();

                            switch (_typeName_TSInputControl.Split('[')[0])
                            {
                                default:
                                    break;

                                case "Array of Numbers":
                                    HTuple _hInputControls_Number = new HTuple();
                                    for (int j = 0; j < _Num_TSInputControl; j++)
                                    {
                                        long _number = (long)_TS_InputControl[i].GetValNumberByOffset(j, 0);
                                        _hInputControls_Number.Append(_number);
                                    }
                                    hInputControls.Add(_hInputControls_Number);
                                    break;

                                case "Array of Strings":
                                    HTuple _hInputControls_String = new HTuple();
                                    for (int j = 0; j < _Num_TSInputControl; j++)
                                    {
                                        string _string = _TS_InputControl[i].GetValStringByOffset(j, 0);
                                        _hInputControls_String.Append(_string);
                                    }
                                    hInputControls.Add(_hInputControls_String);
                                    break;

                                case "Array of Booleans":
                                    HTuple _hInputControls_Bool = new HTuple();
                                    for (int j = 0; j < _Num_TSInputControl; j++)
                                    {
                                        bool _bool = _TS_InputControl[i].GetValBooleanByOffset(j, 0);
                                        _hInputControls_Bool.Append(_bool.ToString());
                                    }
                                    hInputControls.Add(_hInputControls_Bool);
                                    break;
                            }
                        }
                    }
                    else
                    {
                        ErrorCode = -1;
                        ErrorText = procedureName + "：CallProcedure Fail!，hProcedure输入参数(InputControl)个数与Locals对应的参数个数不一致！";
                        //  Trace.Error(ErrorText);
                        return false;
                    }
                }

                //3、传入到CallProcedure，运行
                HTupleVector hTupleVector = new HTupleVector(1);
                for (int i = 0; i < hInputControls.Count; i++)
                {
                    hTupleVector[i] = new HTupleVector(hInputControls[i]);
                }

                bool InitState = base.CallProcedure(procedureName, hInputIconics.ToArray(), out HObject[] hOutputIconics, hTupleVector, out HTupleVector hOutputControls, out int hErrorCode, out string hErrorMsg);
                _hErrorMsg = ErrorText;
                int _hOutputIconicsLength = hOutputIconics.Length;
                int _NumOutputIconics = OutputIconics.GetNumSubProperties("");
                int _hOutputControlsLength = hOutputControls.Length;
                int _NumOutputControls = OutputControls.GetNumSubProperties("");

                //4、OutputIconic变量输出
                if (_hOutputIconicsLength != 0)
                {
                    if (_hOutputIconicsLength == _NumOutputIconics)
                    {
                        //获取hProcedure输出的结果，传入到TestStand---Locals的PropertyObject
                        PropertyObject[] _TS_OutputIconic = OutputIconics.GetSubProperties("", 0);
                        for (int i = 0; i < _hOutputIconicsLength; i++)
                        {
                            int _Num_hOutputIconic = hOutputIconics[i].CountObj();
                            _TS_OutputIconic[i].SetNumElements(_Num_hOutputIconic);
                            PropertyObjectType _type_TSOutputIconic = _TS_OutputIconic[i].Type;
                            string _typeName_TSOutputIconic = _type_TSOutputIconic.DisplayString;
                            switch (_typeName_TSOutputIconic.Split('[')[0])
                            {
                                default:
                                    break;

                                case "Array of Numbers":
                                    for (int j = 0; j < _Num_hOutputIconic; j++)
                                    {
                                        HOperatorSet.SerializeObject(hOutputIconics[i], out HTuple serializedHandle);
                                        _TS_OutputIconic[i].SetValNumberByOffset(j, 0, serializedHandle);
                                    }
                                    break;

                                case "Array of Strings":
                                    for (int j = 0; j < _Num_hOutputIconic; j++)
                                    {
                                        _TS_OutputIconic[i].SetValStringByOffset(j, 0, hOutputControls[i].T[j]);
                                    }
                                    break;

                                case "Array of Booleans":
                                    for (int j = 0; j < _Num_hOutputIconic; j++)
                                    {
                                        _TS_OutputIconic[i].SetValBooleanByOffset(j, 0, hOutputControls[i].T[j]);
                                    }
                                    break;
                            }
                        }
                    }
                    else
                    {
                        ErrorCode = -1;
                        ErrorText = procedureName + "：CallProcedure Fail!，hProcedure输出参数(OutputIconic)个数与Locals对应的参数个数不一致！";
                        // Trace.Error(ErrorText);
                        return false;
                    }
                }

                //5、OutputControl变量输出
                if (_hOutputControlsLength != 0)
                {
                    if (_hOutputControlsLength == _NumOutputControls)
                    {
                        //获取hProcedure输出的结果，传入到TestStand---Locals的PropertyObject
                        PropertyObject[] _TS_OutputControl = OutputControls.GetSubProperties("", 0);
                        for (int i = 0; i < _hOutputControlsLength; i++)
                        {
                            int _Num_hOutputControl = hOutputControls[i].T.Length;
                            _TS_OutputControl[i].SetNumElements(_Num_hOutputControl);
                            PropertyObjectType _type_TSOutputControl = _TS_OutputControl[i].Type;
                            string _typeName_TSOutputControl = _type_TSOutputControl.DisplayString;
                            switch (_typeName_TSOutputControl.Split('[')[0])
                            {
                                default:
                                    break;

                                case "Array of Numbers":
                                    for (int j = 0; j < _Num_hOutputControl; j++)
                                    {
                                        var htuple = hOutputControls[i].T;
                                        double d = htuple[j].D;
                                        _TS_OutputControl[i].SetValNumberByOffset(j, 0, d);
                                    }
                                    break;

                                case "Array of Strings":
                                    for (int j = 0; j < _Num_hOutputControl; j++)
                                    {
                                        try
                                        {
                                            var htuple = hOutputControls[i].T;
                                            string d = htuple[j].S;
                                            _TS_OutputControl[i].SetValStringByOffset(j, 0, d);
                                        }
                                        catch (Exception ex)
                                        {

                                        }

                                    }
                                    break;

                                case "Array of Booleans":
                                    for (int j = 0; j < _Num_hOutputControl; j++)
                                    {
                                        var htuple = hOutputControls[i].T;
                                        bool d = Convert.ToBoolean(htuple[j].S);
                                        _TS_OutputControl[i].SetValBooleanByOffset(j, 0, d);
                                    }
                                    break;
                            }
                        }
                    }
                    else
                    {
                        ErrorCode = -1;
                        ErrorText = procedureName + "：CallProcedure Fail!，hProcedure输出参数(OutputControl)个数与Locals对应的参数个数不一致！";
                        //Trace.Error(ErrorText);
                        return false;
                    }
                }

                ErrorCode = hErrorCode;
                ErrorText = hErrorMsg;
                if (ErrorCode == -1)
                {
                    //Trace.Error(ErrorMsg);
                }
                else
                {
                    // Trace.Info(procedureName + "：CallProcedure Success!");
                }
                return InitState;
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = procedureName + "：" + _hErrorMsg + ",引发后续异常：" + ex.Message + ex.StackTrace;
                //   Trace.Error(ErrorMsg);
                return false;
            }






        }




    }
}
